{-# LANGUAGE TypeOperators              #-}
{-# OPTIONS -Wall #-}

--------------------------------------------------------------------------------
-- |
-- Module      :  Orca.Language.SignalGenerators
-- Copyright   :  (c) Stephen Tetley 2013
-- License     :  BSD3
--
-- Maintainer  :  stephen.tetley@gmail.com
-- Stability   :  unstable
-- Portability :  GHC
--
-- Signal generating opcodes.
--
--------------------------------------------------------------------------------

module Orca.Language.SignalGenerators
  (

  -- * Linear and exponential generators
    line
  , expon
  , linseg
  , linsegr
  , expseg
  , expsegr
  , expsega
  , transeg

  , adsr
  , adsr_

  , madsr
  , madsr_
  , xadsr
  , xadsr_
  , mxadsr
  , mxadsr_

  -- * Table access
  , table
  , table_

  , tablei
  , tablei_
  
  , table3
  , table3_

  , oscil1
  , oscil1i
  , osciln

  -- * Phasors
  , phasor
  , phasor_
  , phasorbnk
  , phasorbnk_


  -- * Basic oscillators
  , oscil
  , oscil_
  , oscili
  , oscili_
  , oscil3
  , oscil3_
  , poscil
  , poscil_
  , poscil3
  , poscil3_
  , lfo
  , lfo_

  -- * Dynamic spectrum oscillators
  , buzz
  , buzz_
  , gbuzz
  , gbuzz_
  , vco

  -- * Additive synthesis / resynthesis
  , adsyn
  , adsynt
  , adsynt_
  , hsboscil
  , hsboscil_

  -- * FM synthesis
  , foscil
  , foscil_
  , foscili
  , foscili_
  , fmvoice
  , fmbell
  , fmrhode
  , fmwurlie
  , fmmetal
  , fmb3
  , fmpercfl

  -- * Sample playback - full spec versions todo
  , loscil
  , loscilS
  , loscil3
  , loscil3S
  , lposcil
  , lposcil3

  -- * Granular synthesis
  , fof
  , fof2
  , fog
  , grain
  , grain2
  , grain3
  , granule
  , partikkel

  -- * Models and emulations
  , moog
  , shaker
  , marimba
  , vibes
  , mandol
  , gogobel
  , voice
  , lorenz
  , planet

  -- * Random noise generators
  , rand
  , randh
  , randi
  , linrand
  , trirand
  , exprand
  , bexprand
  , cauchy
  , pcauchy
  , poisson
  , gauss
  , weibull
  , betarand
  , unirand

  -- * Waveguide physical modeling
  , pluck
  , repluck
  , wgbow
  , wgbowedbar
  , wgbrass
  , wgclar
  , wgflute
  , wgpluck
  , wgpluck2
  , wguide1
  , wguide2    
  ) where


import Orca.Language.Prim
import Orca.Prim.Syntax


--------------------------------------------------------------------------------
-- Linear and Exponential generators



line :: KA_Signal a => IFloat -> IFloat -> IFloat -> GenSig a
line ia idur1 ib = 
    opcode1 "line" [ getPExpr ia, getPExpr idur1
                   , getPExpr ib ]

expon :: KA_Signal a => IFloat -> IFloat -> IFloat -> GenSig a
expon ia idur1 ib = 
    opcode1 "expon" [ getPExpr ia, getPExpr idur1
                    , getPExpr ib ]



linseg :: KA_Signal a 
       => IFloat -> [IFloat ::: IFloat] -> GenSig a
linseg ia xss =  
    opcode1 "linseg" $ getPExpr ia : concatMap fn xss
  where
    fn (idur ::: ib) = [getPExpr idur, getPExpr ib]

    


linsegr :: KA_Signal a 
        => IFloat -> [IFloat ::: IFloat] -> IFloat ->  IFloat 
        -> GenSig a
linsegr ia xss irel iz =
    opcode1 "linsegr" $ getPExpr ia : concatMap fn xss ++ release
  where
    fn (idur ::: ib) = [getPExpr idur, getPExpr ib]
    release          = [getPExpr irel, getPExpr iz]



expseg :: KA_Signal a 
       => IFloat -> [IFloat ::: IFloat] -> GenSig a
expseg ia xss = 
    opcode1 "expseg" $ getPExpr ia : concatMap fn xss
  where
    fn (idur ::: ib) = [getPExpr idur, getPExpr ib]


expsegr :: KA_Signal a
        => IFloat -> [IFloat ::: IFloat] -> IFloat -> IFloat 
        -> GenSig a
expsegr ia xss irel iz = 
    opcode1 "expsegr" $ getPExpr ia : concatMap fn xss ++ release
  where
    fn (idur ::: ib) = [getPExpr idur, getPExpr ib]
    release          = [ getPExpr irel, getPExpr iz ]


expsega :: IFloat -> [IFloat ::: IFloat] -> GenASig
expsega ia xss =
    opcode1 "expsega" $ getPExpr ia : concatMap fn xss 
  where
    fn (idur ::: ib) = [getPExpr idur, getPExpr ib]
 

transeg :: KA_Signal a 
        => IFloat -> [IFloat ::: IFloat ::: IFloat] -> GenSig a
transeg ia xss = 
    opcode1 "transeg" $ getPExpr ia : concatMap fn xss 
  where
    fn (idur ::: (itype ::: ib)) = [ getPExpr idur, getPExpr itype
                                   , getPExpr ib ]


adsr :: KA_Signal a => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
adsr iatt idec islev irel = 
    opcode1 "adsr" [ getPExpr iatt,  getPExpr idec
                   , getPExpr islev, getPExpr irel ]
                   


adsr_ :: KA_Signal a 
      => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
      -> GenSig a
adsr_ iatt idec islev irel idel = 
    opcode1 "adsr" [ getPExpr iatt,  getPExpr idec
                   , getPExpr islev, getPExpr irel
                   , getPExpr idel ]

madsr :: KA_Signal a
      => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
madsr iatt idec islev irel = 
    opcode1 "madsr" [ getPExpr iatt,  getPExpr idec
                    , getPExpr islev, getPExpr irel ]


madsr_ :: KA_Signal a
       => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
       -> GenSig a
madsr_ iatt idec islev irel idel = 
    opcode1 "madsr" [ getPExpr iatt,  getPExpr idec
                    , getPExpr islev, getPExpr irel
                    , getPExpr idel ]


xadsr :: KA_Signal a
      => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
xadsr iatt idec islev irel = 
    opcode1 "xadsr" [ getPExpr iatt,  getPExpr idec
                    , getPExpr islev, getPExpr irel ]


xadsr_ :: KA_Signal a 
       => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
       -> GenSig a
xadsr_ iatt idec islev irel idel = 
    opcode1 "xadsr" [ getPExpr iatt,  getPExpr idec
                    , getPExpr islev, getPExpr irel
                    , getPExpr idel ]


mxadsr :: KA_Signal a
       => IFloat -> IFloat -> IFloat -> IFloat -> GenSig a
mxadsr iatt idec islev irel = 
    opcode1 "mxadsr" [ getPExpr iatt,  getPExpr idec
                     , getPExpr islev, getPExpr irel ]


mxadsr_ :: KA_Signal a
         => IFloat -> IFloat -> IFloat -> IFloat -> IFloat 
         -> GenSig a
mxadsr_ iatt idec islev irel idel = 
    opcode1 "mxadsr" [ getPExpr iatt,  getPExpr idec
                     , getPExpr islev, getPExpr irel
                     , getPExpr idel ]

--------------------------------------------------------------------------------
-- Table access


-- | Note - index not an Int... 
--
table :: IKA_Signal a => Sig a -> TableIx -> GenSig a
table xndx ifn = 
    opcode1 "table" [ getPExpr xndx,  getPExpr ifn ]

table_ :: IKA_Signal a 
       => Sig a -> TableIx -> IFloat -> IFloat -> IFloat 
       -> GenSig a
table_ xndx ifn ixmode ixoff iwrap = 
    opcode1 "table" [ getPExpr xndx,   getPExpr ifn
                    , getPExpr ixmode, getPExpr ixoff
                    , getPExpr iwrap ]


tablei :: IKA_Signal a => Sig a -> TableIx -> GenSig a
tablei xndx ifn = 
    opcode1 "tablei" [ getPExpr xndx,  getPExpr ifn ]

tablei_ :: IKA_Signal a
        => Sig a -> TableIx -> IFloat -> IFloat -> IFloat 
        -> GenSig a
tablei_ xndx ifn ixmode ixoff iwrap = 
    opcode1 "tablei" [ getPExpr xndx,   getPExpr ifn
                     , getPExpr ixmode, getPExpr ixoff
                     , getPExpr iwrap ]



table3 :: IKA_Signal a => Sig a -> TableIx -> GenSig a
table3 xndx ifn = 
    opcode1 "table" [ getPExpr xndx,  getPExpr ifn ]


table3_ :: IKA_Signal a
        => Sig a -> TableIx -> IFloat -> IFloat -> IFloat 
        -> GenSig a
table3_ xndx ifn ixmode ixoff iwrap = 
    opcode1 "table3" [ getPExpr xndx,   getPExpr ifn
                     , getPExpr ixmode, getPExpr ixoff
                     , getPExpr iwrap ]




--------------------------------------------------------------------------------
--


oscil1 :: IFloat -> KSig -> IFloat -> IInt -> GenKSig
oscil1 idel kamp idur ifn = 
    opcode1 "oscil1" [ getPExpr idel, getPExpr kamp
                     , getPExpr idur, getPExpr ifn ]
         


oscil1i :: IFloat -> KSig -> IFloat -> IInt -> GenKSig
oscil1i idel kamp idur ifn = 
    opcode1 "oscil1i" [ getPExpr idel, getPExpr kamp
                      , getPExpr idur, getPExpr ifn ]


osciln :: KSig -> IFloat -> IInt -> IFloat -> GenKSig
osciln kamp ifrq ifn itimes = 
    opcode1 "osciln" [ getPExpr kamp, getPExpr ifrq
                     , getPExpr ifn,  getPExpr itimes ]


--------------------------------------------------------------------------------
-- Phasors

-- class CPhasor rate where


phasor :: KA_Signal a => Sig r1 -> GenSig a
phasor xcps = 
    opcode1 "phasor" [ getPExpr xcps ]

phasor_ :: KA_Signal a => Sig r1 -> IFloat -> GenSig a
phasor_ xcps iphs = 
    opcode1 "phasor" [ getPExpr xcps, getPExpr iphs ]


phasorbnk :: KA_Signal a 
          => Sig r1 -> KSig -> IFloat -> GenSig a
phasorbnk xcps kindx icnt = 
    opcode1 "phasorbnk" [ getPExpr xcps, getPExpr kindx
                        , getPExpr icnt ]


phasorbnk_  :: KA_Signal a 
            => Sig r1 -> KSig -> IFloat -> IFloat 
            -> GenSig a
phasorbnk_ xcps kindx icnt iphs = 
    opcode1 "phasorbnk" [ getPExpr xcps, getPExpr kindx
                        , getPExpr icnt, getPExpr iphs ]


--------------------------------------------------------------------------------
-- Basic oscillators


-- | upsample amp cps when necessary.
-- 
oscil :: KA_Signal a 
      => Sig a -> Sig a -> TableIx -> GenSig a
oscil xamp xcps ifn = 
    opcode1 "oscil" [ getPExpr xamp, getPExpr xcps
                    , getPExpr ifn ]


oscil_ :: KA_Signal a
       => Sig a -> Sig a -> TableIx -> IFloat -> GenSig a
oscil_ xamp xcps ifn iphs = 
    opcode1 "oscil" [ getPExpr xamp, getPExpr xcps
                    , getPExpr ifn,  getPExpr iphs ]




-- | Prefer @oscil@ rather than this one...
--
oscili :: KA_Signal a
       => Sig a -> Sig a -> IInt -> GenSig a
oscili xamp xcps ifn = 
    opcode1 "oscili" [ getPExpr xamp, getPExpr xcps
                     , getPExpr ifn ]


oscili_ :: KA_Signal a
        => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
oscili_ xamp xcps ifn iphs = 
    opcode1 "oscili" [ getPExpr xamp, getPExpr xcps
                     , getPExpr ifn,  getPExpr iphs ]


oscil3 :: KA_Signal a => Sig a -> Sig a -> IInt -> GenSig a
oscil3 xamp xcps ifn = 
    opcode1 "oscil3"  [ getPExpr xamp, getPExpr xcps
                      , getPExpr ifn ]


oscil3_ :: KA_Signal a 
        => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
oscil3_ xamp xcps ifn iphs = 
    opcode1 "oscil3" [ getPExpr xamp, getPExpr xcps
                    , getPExpr ifn,  getPExpr iphs ]



poscil :: KA_Signal a 
       => Sig a -> Sig a -> IInt -> GenSig a
poscil xamp xcps ift = 
    opcode1 "poscil" [ getPExpr xamp, getPExpr xcps
                     , getPExpr ift ]

poscil_ :: KA_Signal a 
        => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
poscil_ xamp xcps ift iphs = 
    opcode1 "poscil" [ getPExpr xamp, getPExpr xcps
                     , getPExpr ift,  getPExpr iphs ]


poscil3 :: KA_Signal a => Sig a -> Sig a -> IInt -> GenSig a
poscil3 xamp xcps ift = 
    opcode1 "poscil3" [ getPExpr xamp, getPExpr xcps
                      , getPExpr ift ]



poscil3_ :: KA_Signal a 
         => Sig a -> Sig a -> IInt -> IFloat -> GenSig a
poscil3_ xamp xcps ift iphs = 
    opcode1 "poscil3" [ getPExpr xamp, getPExpr xcps
                      , getPExpr ift,  getPExpr iphs ]



lfo :: KA_Signal a => Sig a -> Sig a -> GenSig a
lfo xamp xcps = 
    opcode1 "lfo" [ getPExpr xamp, getPExpr xcps ]


lfo_ :: KA_Signal a => Sig a -> Sig a -> IFloat -> GenSig a
lfo_ xamp xcps itype = 
    opcode1 "lfo" [ getPExpr xamp, getPExpr xcps
                  , getPExpr itype ]

--------------------------------------------------------------------------------
-- Dynamic spectrum oscillators

-- TODO - what does the x prefix convention mean for Csound?



-- | upsample @xamp@ and @xps@ where necessary.
--
buzz :: ASig -> ASig -> KSig -> IInt -> GenASig
buzz xamp xcps knh ifn = 
    opcode1 "buzz" [ getPExpr xamp, getPExpr xcps
                   , getPExpr knh,  getPExpr ifn ]


-- | upsample @xamp@ and @xps@ where necessary.
--
buzz_ :: ASig -> ASig -> KSig 
      -> IInt -> IFloat -> GenASig
buzz_ xamp xcps knh ifn iphs = 
    opcode1 "buzz" [ getPExpr xamp, getPExpr xcps
                   , getPExpr knh,  getPExpr ifn
                   , getPExpr iphs ]



gbuzz :: ASig -> ASig -> KSig -> KSig 
      -> KSig -> IInt -> GenASig
gbuzz xamp xcps knh klh kr ifn = 
    opcode1 "gbuzz" [ getPExpr xamp, getPExpr xcps
                    , getPExpr knh,  getPExpr klh
                    , getPExpr kr,   getPExpr ifn ]
 


gbuzz_ :: ASig -> ASig -> KSig 
       -> KSig -> KSig -> IInt -> IFloat 
       -> GenASig
gbuzz_ xamp xcps knh klh kr ifn iphs = 
    opcode1 "gbuzz" [ getPExpr xamp, getPExpr xcps
                    , getPExpr knh,  getPExpr klh
                    , getPExpr kr,   getPExpr ifn
                    , getPExpr iphs ]

vco :: KSig -> KSig -> IFloat -> KSig 
    -> TableIx -> IFloat -> GenASig
vco kamp kfqc iwave kpw ifn imaxd = 
    opcode1 "vco" [ getPExpr kamp,  getPExpr kfqc
                  , getPExpr iwave, getPExpr kpw
                  , getPExpr ifn,   getPExpr imaxd ]


--------------------------------------------------------------------------------
-- Additive synthesis / resynthesis


adsyn :: KSig -> KSig -> KSig -> IString -> GenASig
adsyn kamod kfmod ksmod ifilcod = 
    opcode1 "adsyn" [ getPExpr kamod, getPExpr kfmod
                    , getPExpr ksmod, getPExpr ifilcod ]
    

adsynt :: KSig -> KSig 
       -> TableIx -> TableIx -> TableIx -> IFloat -> GenASig
adsynt kamp kcps iwfn ifreqfn iampfn icnt = 
    opcode1 "adsynt" [ getPExpr kamp,   getPExpr kcps
                     , getPExpr iwfn,   getPExpr ifreqfn
                     , getPExpr iampfn, getPExpr icnt ]


adsynt_ :: KSig -> KSig 
        -> TableIx -> TableIx -> TableIx -> IFloat -> IFloat 
        -> GenASig
adsynt_ kamp kcps iwfn ifreqfn iampfn icnt iphs = 
    opcode1 "adsynt" [ getPExpr kamp,   getPExpr kcps
                     , getPExpr iwfn,   getPExpr ifreqfn
                     , getPExpr iampfn, getPExpr icnt
                     , getPExpr iphs ]

hsboscil :: KSig -> KSig -> KSig 
         -> IFloat -> TableIx -> TableIx -> GenASig
hsboscil kamp ktone kbrite ibasfreq iwnfn ioctfn = 
    opcode1 "hsboscil" [ getPExpr kamp,    getPExpr ktone
                       , getPExpr kbrite,  getPExpr ibasfreq
                       , getPExpr iwnfn,   getPExpr ioctfn ]

hsboscil_ :: KSig -> KSig -> KSig 
          -> IFloat -> TableIx -> TableIx -> IFloat -> IFloat
          -> GenASig
hsboscil_ kamp ktone kbrite ibasfreq iwnfn ioctfn ioctcnt iphs = 
    opcode1 "hsboscil" [ getPExpr kamp,    getPExpr ktone
                       , getPExpr kbrite,  getPExpr ibasfreq
                       , getPExpr iwnfn,   getPExpr ioctfn
                       , getPExpr ioctcnt, getPExpr iphs ]


--------------------------------------------------------------------------------
-- FM Synthesis



foscil :: ASig -> KSig -> KSig -> KSig -> KSig -> TableIx
       -> GenASig
foscil xamp kcps kcar kmod kndx ifn = 
    opcode1 "foscil" [ getPExpr xamp, getPExpr kcps
                     , getPExpr kcar, getPExpr kmod
                     , getPExpr kndx, getPExpr ifn ]


foscil_ :: ASig -> KSig -> KSig 
        -> KSig -> KSig -> TableIx -> IFloat 
        -> GenASig
foscil_ xamp kcps kcar kmod kndx ifn iphs = 
    opcode1 "foscil" [ getPExpr xamp, getPExpr kcps
                     , getPExpr kcar, getPExpr kmod
                     , getPExpr kndx, getPExpr ifn
                     , getPExpr iphs ]



foscili :: ASig -> KSig -> KSig 
        -> KSig -> KSig -> TableIx
        -> GenASig
foscili xamp kcps kcar kmod kndx ifn = 
    opcode1 "foscili" [ getPExpr xamp, getPExpr kcps
                      , getPExpr kcar, getPExpr kmod
                      , getPExpr kndx, getPExpr ifn ]


-- | Upsample @xamp@ if necessary.
--
foscili_ :: ASig -> KSig -> KSig 
         -> KSig -> KSig -> TableIx -> IFloat 
         -> GenASig
foscili_ xamp kcps kcar kmod kndx ifn iphs = 
    opcode1 "foscili" [ getPExpr xamp, getPExpr kcps
                      , getPExpr kcar, getPExpr kmod
                      , getPExpr kndx, getPExpr ifn
                      , getPExpr iphs ]


fmvoice :: KSig -> KSig -> KSig 
        -> KSig -> KSig -> KSig
        -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
        -> GenASig
fmvoice kamp kfreq kvowel ktilt kvibamt kvibrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmvoice" [ getPExpr kamp,    getPExpr kfreq
                      , getPExpr kvowel,  getPExpr ktilt
                      , getPExpr kvibamt, getPExpr kvibrate
                      , getPExpr ifn1,    getPExpr ifn2
                      , getPExpr ifn3,    getPExpr ifn4
                      , getPExpr ifnv ]

fmbell :: KSig -> KSig -> KSig 
       -> KSig -> KSig -> KSig
       -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
       -> GenASig
fmbell kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmbell" [ getPExpr kamp,    getPExpr kfreq
                     , getPExpr kc1,     getPExpr kc2
                     , getPExpr kvdepth, getPExpr kvrate
                     , getPExpr ifn1,    getPExpr ifn2
                     , getPExpr ifn3,    getPExpr ifn4
                     , getPExpr ifnv ]


fmrhode :: KSig -> KSig -> KSig 
        -> KSig -> KSig -> KSig
        -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
        -> GenASig
fmrhode kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmrhode" [ getPExpr kamp,    getPExpr kfreq
                      , getPExpr kc1,     getPExpr kc2
                      , getPExpr kvdepth, getPExpr kvrate
                      , getPExpr ifn1,    getPExpr ifn2
                      , getPExpr ifn3,    getPExpr ifn4
                      , getPExpr ifnv ]

fmwurlie :: KSig -> KSig -> KSig 
         -> KSig -> KSig -> KSig
         -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
         -> GenASig
fmwurlie kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmwurlie" [ getPExpr kamp,    getPExpr kfreq
                       , getPExpr kc1,     getPExpr kc2
                       , getPExpr kvdepth, getPExpr kvrate
                       , getPExpr ifn1,    getPExpr ifn2
                       , getPExpr ifn3,    getPExpr ifn4
                       , getPExpr ifnv ]


fmmetal :: KSig -> KSig -> KSig 
        -> KSig -> KSig -> KSig
        -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
        -> GenASig
fmmetal kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmmetal" [ getPExpr kamp,    getPExpr kfreq
                      , getPExpr kc1,     getPExpr kc2
                      , getPExpr kvdepth, getPExpr kvrate
                      , getPExpr ifn1,    getPExpr ifn2
                      , getPExpr ifn3,    getPExpr ifn4
                      , getPExpr ifnv ]


fmb3 :: KSig -> KSig -> KSig 
     -> KSig -> KSig -> KSig
     -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
     -> GenASig
fmb3 kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmb3" [ getPExpr kamp,    getPExpr kfreq
                   , getPExpr kc1,     getPExpr kc2
                   , getPExpr kvdepth, getPExpr kvrate
                   , getPExpr ifn1,    getPExpr ifn2
                   , getPExpr ifn3,    getPExpr ifn4
                   , getPExpr ifnv ]

fmpercfl :: KSig -> KSig -> KSig 
         -> KSig -> KSig -> KSig        
         -> TableIx -> TableIx -> TableIx -> TableIx -> TableIx
         -> GenASig
fmpercfl kamp kfreq kc1 kc2 kvdepth kvrate ifn1 ifn2 ifn3 ifn4 ifnv = 
    opcode1 "fmpercfl" [ getPExpr kamp,    getPExpr kfreq
                       , getPExpr kc1,     getPExpr kc2
                       , getPExpr kvdepth, getPExpr kvrate
                       , getPExpr ifn1,    getPExpr ifn2
                       , getPExpr ifn3,    getPExpr ifn4
                       , getPExpr ifnv ]


--------------------------------------------------------------------------------
-- Sample playback

-- Note - it seems idiomatic to want a stereo version with only
-- the mandatory args...


-- | Note - use 1 for ibase and kcps if the frequency is not known.
--
loscil :: ASig -> KSig -> TableIx 
       -> GenASig
loscil xamp kcps ifn = 
    opcode1 "loscil" [ getPExpr xamp,    getPExpr kcps
                     , getPExpr ifn ]



-- | Stereo version of 'loscil'.
--
-- Note - use 1 for ibase and kcps if the frequency is not known.
--
loscilS :: ASig -> KSig -> TableIx
        -> GenSig2 ARate
loscilS xamp kcps ifn = 
    opcode1 "loscil" [ getPExpr xamp,    getPExpr kcps
                     , getPExpr ifn ]




-- | Note - use 1 for ibase and kcps if the frequency is not known.
-- upsample @xamp@ if necessary.
--
loscil3 :: ASig -> KSig -> TableIx 
        -> GenASig
loscil3 xamp kcps ifn = 
    opcode1 "loscil3" [ getPExpr xamp, getPExpr kcps
                      , getPExpr ifn ]



-- | Stereo version of 'loscil3'.
--
-- Note - use 1 for ibase and kcps if the frequency is not known.
-- upsample @xamp@ if necessary.
--
loscil3S :: ASig -> KSig -> TableIx
         -> GenSig2 ARate
loscil3S xamp kcps ifn = 
    opcode1 "loscil3" [ getPExpr xamp, getPExpr kcps
                      , getPExpr ifn ]



lposcil :: KSig -> KSig 
        -> KSig -> KSig -> TableIx
        -> GenASig
lposcil kamp kfreqratio kloop kend ift = 
    opcode1 "lposcil" [ getPExpr kamp,  getPExpr kfreqratio
                      , getPExpr kloop, getPExpr kend
                      , getPExpr ift ]



lposcil3 :: KSig -> KSig 
         -> KSig -> KSig -> TableIx
         -> GenASig
lposcil3 kamp kfreqratio kloop kend ift = 
    opcode1 "lposcil3" [ getPExpr kamp,  getPExpr kfreqratio
                       , getPExpr kloop, getPExpr kend
                       , getPExpr ift ]


--------------------------------------------------------------------------------
-- Granular synthesis

fof :: IKA_Signal a
    => Sig a  -> Sig a  -> Sig a
    -> KSig -> KSig -> KSig
    -> KSig -> KSig -> IInt
    -> TableIx -> TableIx -> IFloat
    -> GenASig
fof xamp xfund xform koct kband kris kdur kdec iolaps ifna ifnb itotdur = 
    opcode1 "fof" [ getPExpr xamp,   getPExpr xfund
                  , getPExpr xform,  getPExpr koct
                  , getPExpr kband,  getPExpr kris
                  , getPExpr kdur,   getPExpr kdec
                  , getPExpr iolaps, getPExpr ifna
                  , getPExpr ifnb,   getPExpr itotdur ]




fof2 :: IKA_Signal a
     => Sig a  -> Sig a  -> Sig a
     -> KSig -> KSig -> KSig
     -> KSig -> KSig -> IInt
     -> TableIx -> TableIx -> IFloat
     -> KSig -> KSig
     -> GenASig
fof2 xamp xfund xform koct kband kris kdur kdec iolaps ifna ifnb itotdur 
     kphs kgliss = 
    opcode1 "fof2" [ getPExpr xamp,   getPExpr xfund
                   , getPExpr xform,  getPExpr koct
                   , getPExpr kband,  getPExpr kris
                   , getPExpr kdur,   getPExpr kdec
                   , getPExpr iolaps, getPExpr ifna
                   , getPExpr ifnb,   getPExpr itotdur 
                   , getPExpr kphs,   getPExpr kgliss ]



-- | 
--
-- > fog : xamp * xdens * xtrans * aspd * 
-- >       koct * kband * kris * kdur * kdec *
-- >       iolaps * ifna * ifnb * itotdur
-- >      -> ares
--
-- Note - kband etc. are not perhaps signals. 
-- Or maybe they are see @grain@...
--
fog             :: IKA_Signal a
                => Sig a -> Sig a -> Sig a
                -> Sig a -> KSig -> KSig
                -> KSig -> KSig -> KSig
                -> IFloat -> TableIx -> TableIx 
                -> IFloat
                -> GenASig
fog xamp xdens xtrans xspd koct kband kris kdur kdec iolaps ifna ifnb itotdur = 
    opcode1 "fog" [ getPExpr xamp,   getPExpr xdens
                  , getPExpr xtrans, getPExpr xspd
                  , getPExpr koct,   getPExpr kband
                  , getPExpr kris,   getPExpr kdur
                  , getPExpr kdec,   getPExpr iolaps
                  , getPExpr ifna,   getPExpr ifnb
                  , getPExpr itotdur ]
    
-- | 
-- 
-- > grain : xamp * xpitch * xdens * kampoff * 
-- >         kpitchoff * kgdur * igfn * iwfn * imgdur
-- >        -> ares

grain           :: IKA_Signal a
                => Sig a -> Sig a -> Sig a
                -> KSig -> KSig -> KSig
                -> TableIx -> TableIx -> IFloat
                -> GenASig
grain xamp xpitch xdens kampoff kpitchoff kgdur igfn iwfn imgdur = 
    opcode1 "grain" [ getPExpr xamp,      getPExpr xpitch
                    , getPExpr xdens,     getPExpr kampoff
                    , getPExpr kpitchoff, getPExpr kgdur
                    , getPExpr igfn,      getPExpr iwfn
                    , getPExpr imgdur ]


grain2 :: KSig -> KSig -> KSig -> IInt -> TableIx -> TableIx -> GenASig
grain2 kcps kfmd kgdur iovrlp kfn iwfn = 
    opcode1 "grain2" [ getPExpr kcps,  getPExpr kfmd
                     , getPExpr kgdur, getPExpr iovrlp
                     , getPExpr kfn,   getPExpr iwfn ] 



grain3 :: KSig -> KSig -> KSig -> KSig -> KSig -> KSig
       -> IInt -> TableIx -> TableIx -> KSig -> KSig
       -> GenASig
grain3 kcps kphs kfmd kpmd kgdur kdens imaxovr kfn iwfn kfrpow kprpow = 
    opcode1 "grain3" [ getPExpr kcps,    getPExpr kphs
                     , getPExpr kfmd,    getPExpr kpmd
                     , getPExpr kgdur,   getPExpr kdens
                     , getPExpr imaxovr, getPExpr kfn
                     , getPExpr iwfn,    getPExpr kfrpow
                     , getPExpr kprpow ] 

-- |
-- 
-- > granule : xamp * ivoice * iratio * imode * ithd
-- >           ifn * ipshift * igskip * igskip_os * 
-- >           ilength * kgap * igap_os * kgsize * 
-- >           igsize_os * iatt * idec
-- >          -> ares
--
granule         :: IKA_Signal a 
                => Sig a -> IInt -> IFloat
                -> IInt -> IFloat -> TableIx
                -> IInt -> IFloat -> IFloat
                -> IFloat -> KSig -> IFloat 
                -> KSig -> IFloat -> IFloat 
                -> IFloat                
                -> GenASig 
granule xamp ivoice iratio imode ithd ifn ipshift igskip igskip_os
        ilength kgap igap_os kgsize igsize_os iatt idec = 
    opcode1 "granule" [ getPExpr xamp,      getPExpr ivoice
                      , getPExpr iratio,    getPExpr imode
                      , getPExpr ithd,      getPExpr ifn
                      , getPExpr ipshift,   getPExpr igskip
                      , getPExpr igskip_os, getPExpr ilength
                      , getPExpr kgap,      getPExpr igap_os
                      , getPExpr kgsize,    getPExpr igsize_os
                      , getPExpr iatt,      getPExpr idec ]



-- Note - not all k rate values are /signals/ (reals) the can be 
-- function table numbers as well. For these we use TableIx 
-- rather than KSig.

partikkel :: ASig -> KSig -> TableIx -> ASig -> KSig
          -> TableIx -> TableIx -> TableIx -> KSig -> KSig 
          -> KSig -> KSig -> TableIx -> KSig -> KSig
          -> TableIx -> TableIx -> ASig -> TableIx -> KSig 
          -> TableIx -> KSig -> KSig -> KSig -> TableIx
          -> KSig -> TableIx -> TableIx -> TableIx -> TableIx
          -> TableIx -> ASig -> ASig -> ASig -> ASig
          -> KSig -> KSig -> KSig -> KSig -> IInt 
          -> GenASig
partikkel agrainfreq kdistribution idisttab async kenv2amt
          ienv2tab ienv_attack ienv_decay ksustain_amount ka_d_ratio
          kduration kamp igainmasks kwavfreq ksweepshape
          iwavfreqstarttab iwavfreqendtab awavfm ifmamptab kfmenv
          icosine ktraincps knumpartials kchroma ichannelmasks 
          krandommask kwaveform1 kwaveform2 kwaveform3 kwaveform4
          iwaveamptab asamplepos1 asamplepos2 asamplepos3 asamplepos4
          kwavekey1 kwavekey2 kwavekey3 kwavekey4 imax_grains = 
    opcode1 "partikkel" [ getPExpr agrainfreq,      getPExpr kdistribution 
                        , getPExpr idisttab,        getPExpr async
                        , getPExpr kenv2amt,        getPExpr ienv2tab 
                        , getPExpr ienv_attack,     getPExpr ienv_decay
                        , getPExpr ksustain_amount, getPExpr ka_d_ratio
                        , getPExpr kduration,       getPExpr kamp
                        , getPExpr igainmasks,      getPExpr kwavfreq
                        , getPExpr ksweepshape,     getPExpr iwavfreqstarttab
                        , getPExpr iwavfreqendtab,  getPExpr awavfm
                        , getPExpr ifmamptab,       getPExpr kfmenv
                        , getPExpr icosine,         getPExpr ktraincps
                        , getPExpr knumpartials,    getPExpr kchroma
                        , getPExpr ichannelmasks,   getPExpr krandommask
                        , getPExpr kwaveform1,      getPExpr kwaveform2
                        , getPExpr kwaveform3,      getPExpr kwaveform4
                        , getPExpr iwaveamptab,     getPExpr asamplepos1
                        , getPExpr asamplepos2,     getPExpr asamplepos3
                        , getPExpr asamplepos4,     getPExpr kwavekey1
                        , getPExpr kwavekey2,       getPExpr kwavekey3
                        , getPExpr kwavekey4,       getPExpr imax_grains ]




--------------------------------------------------------------------------------
-- Models and emulations

moog :: KSig -> KSig -> KSig 
     -> KSig -> KSig -> KSig
     -> TableIx -> TableIx -> TableIx
     -> GenASig
moog kamp kfreq kfiltq kfiltrate kvibf kvamp iafn iwfn ivfn = 
    opcode1 "moog" [ getPExpr kamp,   getPExpr kfreq
                   , getPExpr kfiltq, getPExpr kfiltrate
                   , getPExpr kvibf,  getPExpr kvamp
                   , getPExpr iafn,   getPExpr iwfn
                   , getPExpr ivfn ]


-- | idecay - default is 0
--
shaker :: KSig -> KSig -> KSig 
       -> KSig -> KSig -> IFloat
       -> GenASig
shaker kamp kfreq kbeans kdamp ktimes idecay = 
    opcode1 "shaker" [ getPExpr kamp,   getPExpr kfreq
                     , getPExpr kbeans, getPExpr kdamp
                     , getPExpr ktimes, getPExpr idecay ]


marimba :: KSig -> KSig -> IFloat -> IFloat 
        -> IInt  -> KSig -> KSig 
        -> TableIx  -> IFloat
        -> GenASig
marimba kamp kfreq ihrd ipos imp kvibf kvamp ivibfn idec = 
    opcode1 "marimba" [ getPExpr kamp,  getPExpr kfreq
                      , getPExpr ihrd,  getPExpr ipos
                      , getPExpr imp,   getPExpr kvibf
                      , getPExpr kvamp, getPExpr ivibfn
                      , getPExpr idec ]

vibes :: KSig -> KSig -> IFloat -> IFloat 
      -> IInt  -> KSig -> KSig   
      -> TableIx  -> IFloat
      -> GenASig
vibes kamp kfreq ihrd ipos imp kvibf kvamp ivibfn idec = 
    opcode1 "vibes" [ getPExpr kamp,  getPExpr kfreq
                      , getPExpr ihrd,  getPExpr ipos
                      , getPExpr imp,   getPExpr kvibf
                      , getPExpr kvamp, getPExpr ivibfn
                      , getPExpr idec ]

-- | iminfreq - default 0
--
mandol :: KSig -> KSig -> KSig 
       -> KSig -> KSig -> KSig 
       -> IInt -> IFloat
       -> GenASig
mandol kamp kfreq kpluck kdetune kgain ksize ifn iminfreq = 
    opcode1 "marimba" [ getPExpr kamp,   getPExpr kfreq
                      , getPExpr kpluck, getPExpr kdetune
                      , getPExpr kgain,  getPExpr ksize
                      , getPExpr ifn,    getPExpr iminfreq ]


gogobel :: KSig  -> KSig 
        -> IFloat -> IFloat -> IFloat 
        -> KSig  -> KSig  -> TableIx
        -> GenASig
gogobel kamp kfreq ihrd ipos imp kvibf kvamp ivfn = 
    opcode1 "gogobel" [ getPExpr kamp,  getPExpr kfreq
                      , getPExpr ihrd,  getPExpr ipos
                      , getPExpr imp,   getPExpr kvibf
                      , getPExpr kvamp, getPExpr ivfn ]


voice :: KSig -> KSig -> KSig 
      -> KSig -> KSig -> KSig
      -> TableIx -> TableIx
      -> GenASig
voice kamp kfreq kphoneme kform kvibf kvamp ifn ivfn = 
    opcode1 "voice" [ getPExpr kamp,     getPExpr kfreq
                    , getPExpr kphoneme, getPExpr kform
                    , getPExpr kvibf,    getPExpr kvamp
                    , getPExpr ifn,      getPExpr ivfn ]

lorenz :: KSig  -> KSig  -> KSig   -> KSig 
       -> IFloat -> IFloat -> IFloat -> IFloat
       -> GenSig3 ARate
lorenz ks kr kb kh ix iy iz iskip =  
    opcode1 "lorenz" [ getPExpr ks, getPExpr kr
                     , getPExpr kb, getPExpr kh
                     , getPExpr ix, getPExpr iy
                     , getPExpr iz, getPExpr iskip ]

planet :: KSig  -> KSig   -> KSig 
       -> IFloat -> IFloat -> IFloat 
       -> IFloat -> IFloat -> IFloat 
       -> IFloat -> IFloat
       -> GenSig3 ARate
planet kmass1 kmass2 ksep ix iy iz ivx ivy ivz idelta ifriction = 
    opcode1 "planet" [ getPExpr kmass1, getPExpr kmass2
                     , getPExpr ksep,   getPExpr ix
                     , getPExpr iy,     getPExpr iz
                     , getPExpr ivx,    getPExpr ivy
                     , getPExpr ivz,    getPExpr idelta
                     , getPExpr ifriction ]



--------------------------------------------------------------------------------
-- Random noise generators



rand :: KA_Signal a => Sig a -> GenSig a
rand xamp = 
    opcode1 "rand" [ getPExpr xamp ]


randh :: KA_Signal a => Sig a -> Sig a -> GenSig a
randh xamp xcps = 
    opcode1 "rand" [ getPExpr xamp, getPExpr xcps ]


randi :: KA_Signal a => Sig a -> Sig a -> GenSig a
randi xamp xcps = 
    opcode1 "rand" [ getPExpr xamp, getPExpr xcps ]



linrand :: IKA_Signal a =>  KSig -> GenSig a
linrand krange = 
    opcode1 "linrand" [ getPExpr krange ]



trirand ::  IKA_Signal a => KSig -> GenSig a
trirand krange = 
    opcode1 "trirand" [ getPExpr krange ]



exprand :: IKA_Signal a => KSig -> GenSig a
exprand krange = 
    opcode1 "exprand" [ getPExpr krange ]


bexprand :: IKA_Signal a => KSig -> GenSig a
bexprand krange = 
    opcode1 "bexprand" [ getPExpr krange ]


cauchy :: IKA_Signal a => KSig -> GenSig a
cauchy kalpha = 
    opcode1 "cauchy" [ getPExpr kalpha ]


pcauchy :: IKA_Signal a => KSig -> GenSig a
pcauchy kalpha = 
    opcode1 "pcauchy" [ getPExpr kalpha ]


poisson :: IKA_Signal a =>  KSig -> GenSig a
poisson klambda = 
    opcode1 "poisson" [ getPExpr klambda ]


gauss :: IKA_Signal a => KSig -> GenSig a
gauss krange = 
    opcode1 "gauss" [ getPExpr krange ]

weibull :: IKA_Signal a => KSig -> KSig -> GenSig a
weibull ksigma ktau = 
   opcode1 "weibull" [ getPExpr ksigma, getPExpr ktau ]


betarand :: IKA_Signal a => KSig -> KSig -> KSig -> GenSig a
betarand krange kalpha kbeta = 
    opcode1 "betarand" [ getPExpr krange, getPExpr kalpha
                       , getPExpr kbeta ]


-- Note - can make IRate value from a KRate value, odd...

unirand :: IKA_Signal a => KSig -> GenSig a
unirand krange = 
    opcode1 "unirand" [ getPExpr krange ]



--------------------------------------------------------------------------------
-- Waveguide physical modeling

pluck  :: KSig -> KSig -> IFloat -> TableIx -> IInt -> GenASig
pluck kamp kcps icps ifn imeth = 
    opcode1 "pluck" [ getPExpr kamp, getPExpr kcps
                    , getPExpr icps, getPExpr ifn
                    , getPExpr imeth ]


repluck :: IFloat -> KSig -> IFloat -> KSig -> KSig -> ASig -> GenASig
repluck iplk kamp icps kpick krefl axcite =
    opcode1 "repluck" [ getPExpr iplk,  getPExpr kamp
                      , getPExpr icps,  getPExpr kpick
                      , getPExpr krefl, getPExpr axcite ]


wgbow :: KSig -> KSig -> KSig -> KSig -> KSig -> KSig -> TableIx -> GenASig
wgbow kamp kfreq kpres krat kvibf kvamp ifn =
    opcode1 "repluck" [ getPExpr kamp,  getPExpr kfreq
                      , getPExpr kpres, getPExpr krat
                      , getPExpr kvibf, getPExpr kvamp
                      , getPExpr ifn ]



wgbowedbar :: KSig -> KSig -> KSig -> KSig -> KSig -> GenASig
wgbowedbar kamp kfreq kpos kbowpres kgain = 
    opcode1 "wgbowedbar" [ getPExpr kamp, getPExpr kfreq
                         , getPExpr kpos, getPExpr kbowpres
                         , getPExpr kgain ]
             


wgbrass :: KSig -> KSig -> KSig -> IFloat -> KSig -> KSig -> TableIx 
        -> GenASig
wgbrass kamp kfreq ktens iatt kvibf kvamp ifn = 
    opcode1 "wgbrass" [ getPExpr kamp,  getPExpr kfreq
                      , getPExpr ktens, getPExpr iatt
                      , getPExpr kvibf, getPExpr kvamp
                      , getPExpr ifn ]

wgclar :: KSig -> KSig -> KSig -> IFloat -> IFloat
       -> KSig -> KSig -> KSig -> TableIx
       -> GenASig
wgclar kamp kfreq kstiff iatt idetk kngain kvibf kvamp ifn = 
    opcode1 "wgclar" [ getPExpr kamp,   getPExpr kfreq
                     , getPExpr kstiff, getPExpr iatt
                     , getPExpr idetk,  getPExpr kngain
                     , getPExpr kvibf,  getPExpr kvamp
                     , getPExpr ifn ]

wgflute :: KSig -> KSig -> KSig -> IFloat -> IFloat
        -> KSig -> KSig -> KSig -> TableIx
       -> GenASig
wgflute kamp kfreq kjet iatt idetk kngain kvibf kvamp ifn = 
    opcode1 "wgflute" [ getPExpr kamp,   getPExpr kfreq
                      , getPExpr kjet,   getPExpr iatt
                      , getPExpr idetk,  getPExpr kngain
                      , getPExpr kvibf,  getPExpr kvamp
                      , getPExpr ifn ]

wgpluck :: IFloat -> IFloat -> KSig -> IFloat -> IFloat -> IFloat -> ASig
        -> GenASig
wgpluck icps iamp kpick iplk idamp ifilt axcite = 
    opcode1 "wgpluck" [ getPExpr icps,  getPExpr iamp
                      , getPExpr kpick, getPExpr iplk
                      , getPExpr idamp, getPExpr ifilt
                      , getPExpr axcite ]

wgpluck2 :: IFloat -> KSig -> IFloat -> KSig -> KSig -> GenASig
wgpluck2 iplk kamp icps kpick krefl = 
    opcode1 "wgpluck2" [ getPExpr iplk, getPExpr kamp
                       , getPExpr icps, getPExpr kpick
                       , getPExpr krefl ]

wguide1 :: KA_Signal a => ASig -> Sig a -> KSig -> KSig -> GenASig
wguide1 asig xfreq kcutoff kfeedback = 
    opcode1 "wguide1" [ getPExpr asig,    getPExpr xfreq
                      , getPExpr kcutoff, getPExpr kfeedback ]


wguide2 :: (KA_Signal a, KA_Signal b)
        => ASig -> Sig a -> Sig b -> KSig -> KSig -> KSig -> KSig -> GenASig
wguide2 asig xfreq1 xfreq2 kcutoff1 kcutoff2 kfeedback1 kfeedback2 =
    opcode1 "wguide2" [ getPExpr asig,      getPExpr xfreq1
                      , getPExpr xfreq2,    getPExpr kcutoff1
                      , getPExpr kcutoff2,  getPExpr kfeedback1
                      , getPExpr  kfeedback2 ]
